/*******************************************************************************
 * Copyright (c) 2012, 2013 XML-Print Project.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     XML-Print Project - initial API and implementation
 ******************************************************************************/
package info.xmlprint.ui.referencesystem;

import info.xmlprint.core.project.PrintProject;
import info.xmlprint.core.referencesystem.AbstractBaseGroup;
import info.xmlprint.core.referencesystem.AbstractBaseItem;
import info.xmlprint.core.referencesystem.ReferenceField;
import info.xmlprint.core.referencesystem.ReferenceFieldGroup;
import info.xmlprint.ui.message.GuiMessages;
import info.xmlprint.ui.widgets.IObserverControl;
import info.xmlprint.ui.widgets.ISetupComposite;
import info.xmlprint.util.FileUtil;
import info.xmlprint.util.ResizeColumns;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;

public class ReferenceFieldSetup extends Composite implements IObserverControl,
		ISetupComposite {

	private class LocalContentProvider implements ITreeContentProvider {

		@Override
		public void dispose() {
		}

		@Override
		public Object[] getChildren(Object parentElement) {
			return null;
		}

		@Override
		public Object[] getElements(Object list) {
			if (list instanceof ReferenceFieldGroup) {
				return ((ReferenceFieldGroup) list).getItems().toArray();
			}
			return null;
		}

		@Override
		public Object getParent(Object element) {
			return null;
		}

		@Override
		public boolean hasChildren(Object element) {
			return false;
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private class LocalLabelProvider implements ITableLabelProvider {

		@Override
		public void addListener(ILabelProviderListener listener) {
		}

		@Override
		public void dispose() {
		}

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object obj, int index) {
			if (obj instanceof ReferenceField) {
				ReferenceField field = (ReferenceField) obj;
				// col name
				if (index == 0)
					return field.getValueOf("name");

				// col xpath
				if (index == 1) {
					String select = field.getValueOf("content-select");
					String contentText;

					if (select.equalsIgnoreCase("0")) {
						contentText = field.getValueOf("content-value-format");
					} else if (select.equalsIgnoreCase("1")) {
						contentText = field.getValueOf("content-value-typo");
					} else {
						contentText = GuiMessages.Fieldinformation_General_XPath
								+ ": ";
						contentText += field.getValueOf("content-xPath");
					}
					return contentText;
				}

				// col counter
				if (index == 2) {
					if (field.getValueOf("content-select").equalsIgnoreCase("1"))
						return "";
					String select = field.getValueOf("counter-select");
					String counterText;
					if (select.equalsIgnoreCase("0")) {
						counterText = GuiMessages.Fieldinformation_General_Attribute
								+ ": ";
						counterText += field.getValueOf("counter-attribute");
					} else {
						counterText = GuiMessages.Fieldinformation_Counter_Continuous
								+ "; "
								+ GuiMessages.Fieldinformation_Counter_InitialValue
								+ ": ";
						counterText += field.getValueOf("counter-startValue");
					}

					return counterText;
				}

				// col reset
				if (index == 3) {
					String select = field.getValueOf("reset-select");
					String resetText;
					if (select.equalsIgnoreCase("0")) {
						resetText = "Nie";
					} else if (select.equalsIgnoreCase("1")) {
						resetText = GuiMessages.Fieldinformation_Field + ": ";
						resetText += field.getValueOf("reset-name");
					} else {
						resetText = GuiMessages.Fieldinformation_General_XPath
								+ ": ";
						resetText += field.getValueOf("reset-xPath");
					}
					return resetText;
				}

				// col title
				if (index == 4) {
					if (field.getValueOf("content-select").equalsIgnoreCase("1"))
						return "";
					String select = field.getValueOf("title-select");
					String titleText = "";
					if (select.equalsIgnoreCase("1")) {
						titleText = GuiMessages.Fieldinformation_General_Attribute;
						titleText += field.getValueOf("title-attribute");
					} else if (select.equalsIgnoreCase("2")) {
						titleText = GuiMessages.Fieldinformation_Title_Content_Element;
					} else if (select.equalsIgnoreCase("3")) {
						titleText = GuiMessages.Fieldinformation_Title_Content_XPath
								+ ": ";
						titleText += field.getValueOf("title-xPath");
					}
					return titleText;
				}

			}
			return null;
		}

		@Override
		public boolean isLabelProperty(Object element, String property) {
			return false;
		}

		@Override
		public void removeListener(ILabelProviderListener listener) {
		}
	}

	private ReferenceFieldComposite fieldComposite;

	private AbstractBaseGroup fieldGroup;

	private Shell fieldShell;

	private TreeViewer treeViewer;

	private PrintProject printProject;

	public ReferenceFieldSetup(Composite parent, int style) {
		super(parent, style);
		this.setLayout(new FillLayout());
		this.addDisposeListener(new DisposeListener() {
			@Override
			public void widgetDisposed(DisposeEvent e) {
				treeViewer.getControl().dispose();
				treeViewer = null;
				if (fieldShell != null && !fieldShell.isDisposed()) {
					fieldShell.dispose();
				}
			}
		});

		initGui();
	}

	private void delItemAction(ReferenceField field) {
		AbstractBaseGroup group = field.getGroup();
		group.remove(field);
		updateControl();
	}

	public AbstractBaseGroup getReferenceGroup() {
		return fieldGroup;
	}

	private void initGui() {
		treeViewer = new TreeViewer(this, SWT.FULL_SELECTION | SWT.MULTI);
		final Tree tree = treeViewer.getTree();
		tree.setHeaderVisible(true);
		tree.setLinesVisible(true);
		TableLayout tableLayout = new TableLayout();
		tree.setLayout(tableLayout);

		TreeColumn nameCol = new TreeColumn(tree, SWT.NONE);
		nameCol.setText(GuiMessages.Fieldinformation_Name);

		TreeColumn contentCol = new TreeColumn(tree, SWT.NONE);
		contentCol.setText(GuiMessages.Fieldinformation_Content);

		TreeColumn counterCol = new TreeColumn(tree, SWT.NONE);
		counterCol.setText(GuiMessages.Fieldinformation_Counter);

		TreeColumn resetCol = new TreeColumn(tree, SWT.NONE);
		resetCol.setText(GuiMessages.Fieldinformation_Reset);

		TreeColumn titleCol = new TreeColumn(tree, SWT.NONE);
		titleCol.setText(GuiMessages.Fieldinformation_Title);

		treeViewer.setContentProvider(new LocalContentProvider() {
		});
		treeViewer.setLabelProvider(new LocalLabelProvider() {
		});

		tree.addListener(SWT.MouseDoubleClick, new Listener() {
			@Override
			public void handleEvent(Event e) {
				TreeItem treeItem = tree.getItem(new Point(e.x, e.y));
				if (treeItem != null) {
					ReferenceField selectedField = (ReferenceField) treeItem
							.getData();
					openFieldEditShell(selectedField);
				} else
					openFieldEditShell(null);
			}
		});

		tree.addListener(SWT.MenuDetect, new Listener() {
			@Override
			public void handleEvent(Event event) {
				final ReferenceField selectedField;

				if (tree.getSelection() == null || tree.getSelectionCount() < 1) {
					selectedField = null;
				} else {
					TreeItem ti = tree.getSelection()[0];
					selectedField = (ReferenceField) ti.getData();
				}

				Menu menu = new Menu(tree.getShell(), SWT.POP_UP);

				MenuItem editItem = new MenuItem(menu, SWT.PUSH);
				editItem.setText(GuiMessages.General_Gui_Edit);
				editItem.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						openFieldEditShell(selectedField);
					}
				});
				if (selectedField == null) {
					editItem.setEnabled(false);
				}

				MenuItem delItem = new MenuItem(menu, SWT.PUSH);
				delItem.setText(GuiMessages.General_Gui_Delete);
				delItem.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						for (AbstractBaseItem field : fieldGroup.getItems()) {
							if (field.equals(selectedField))
								continue;

							if (field.getValueOf("reset-select").trim() // TODO:
																		// Is
																		// the
																		// following
																		// correct?
									.equalsIgnoreCase("0")) {//$NON-NLS-1$
								if (field.getValueOf("reset-attribute").equals(
										field.getValueOf("name"))) {
									MessageDialog
											.openError(
													null,
													"",
													GuiMessages.Stileditor_Error_NameForFieldAlreadyUsed);
									return;
								}
							}

						}

						if (MessageDialog.openConfirm(null, "",
								GuiMessages.Stileditor_Warning_AreYouSure)) {

							delItemAction(selectedField);
						}
					}
				});
				if (selectedField == null) {
					delItem.setEnabled(false);
				}

				new MenuItem(menu, SWT.SEPARATOR);

				MenuItem addItem = new MenuItem(menu, SWT.PUSH);
				addItem.setText(GuiMessages.General_Gui_Add);
				addItem.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						openFieldEditShell(null);
					}
				});
				menu.setVisible(true);
			}
		});

		this.addControlListener(new ResizeColumns(this, tree));
	}

	/*
	 * Eistellungsfenster fuer ausgewaehltes Feld
	 */
	private void openFieldEditShell(ReferenceField field) {
		if (fieldShell == null) {
			fieldShell = new Shell(this.getDisplay(), SWT.CLOSE | SWT.MIN
					| SWT.APPLICATION_MODAL | SWT.RESIZE | SWT.MAX);
			fieldShell.setText(GuiMessages.Fieldinformation_FieldDefinition);
			FileUtil.shellSetCenter(fieldShell);
			fieldShell.setLayout(new GridLayout());
			fieldShell.addListener(SWT.Close, new Listener() {
				public void handleEvent(Event event) {
					fieldShell.setVisible(false);
					event.doit = false;
				}
			});
			fieldComposite = new ReferenceFieldComposite(fieldShell, SWT.NONE);
			fieldComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
			fieldComposite.registerObserver(this);
			fieldComposite.setPrintProject(printProject);
			fieldShell.pack();
		}
		fieldShell.open();
		fieldComposite.setReferenceGroup(fieldGroup);
		fieldComposite.setInput(field);
	}

	@Override
	public void setPrintProject(PrintProject project) {
		printProject = project;
		fieldGroup = printProject.getReferenceFieldGroup();
		treeViewer.setInput(fieldGroup);
	}

	@Override
	public void updateControl() {
		treeViewer.refresh();
	}
}
